package com.db.jschool.logging;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.helpers.MessageFormatter;

/**
 * Simplest, but not good implementation. Anyway the task wasn't about it.
 * @author Artem Nikitin
 *
 */
public class Layout {
	private static final String DEFAULT_PATTERN = "%m%n";
	private final String pattern;
	private static final char WC_MSG = 'm';
	private static final char WC_THREAD_NAME = 't';
	private static final char WC_DATE = 'd';
	private static final char WC_LEVEL = 'l';
	private static final char WC_LOGGER_NAME = 'L';
	private static final char WC_NEW_LINE = 'n';
	private static final char WC_PERCENT = '%';
	
	public Layout() {
		this.pattern = DEFAULT_PATTERN;
	}
	
	public Layout(String pattern) {
		this.pattern = pattern;
	}
	
	public String format(LogRecord lr) {
		return format(pattern, lr);
	}
	
	private String format(String pattern, LogRecord lr) {
		StringBuffer sbuf = new StringBuffer("");
		char[] pttrn = pattern.toCharArray();
		try {
			int i = 0;
			int prev = 0;
			while (i < pttrn.length - 1) {
				while (i < pttrn.length && pttrn[i] != '%') {
					i++;
				}
				
				sbuf.append(pttrn, prev, i - prev);
				i = convert(pttrn, i, sbuf, lr);
				prev = i;
			}
		} catch (IllegalLayoutFormatException e) {
			format(DEFAULT_PATTERN, lr);
		}
		return sbuf.toString();
	}
	
	private int convert(char[] pttrn, int i, StringBuffer sbuffer, LogRecord lr) {
		char conversion = pttrn[i + 1];
		switch (conversion) {
		case WC_MSG:
			String msg = MessageFormatter.arrayFormat(lr.message, lr.fmtArgs).getMessage();
			sbuffer.append(msg);
			return i + 2;
		case WC_THREAD_NAME:
			sbuffer.append(lr.threadName);
			return i + 2;
		case WC_DATE:
			SimpleDateFormat sdf;
			if (pttrn[i + 2] == '{') {
				int j = i + 3;
				while(j < pttrn.length && pttrn[j] != '}') {
					j++;
				}
				 
				if (j >= pttrn.length)
					throw new IllegalLayoutFormatException("Illegal format exception: illegal date format");
				
				sdf = new SimpleDateFormat(new String(pttrn, i + 3, j - i - 3));
				i = j - 1;
			} else {
				sdf = new SimpleDateFormat();
			}
			sbuffer.append(sdf.format(new Date(lr.timeStamp)));
			return i + 2;
		case WC_LEVEL:
			sbuffer.append(lr.level.toString());
			return i + 2;
		case WC_LOGGER_NAME:
			sbuffer.append(lr.loggerName);
			return i + 2;
		case WC_NEW_LINE:
			sbuffer.append("\n");
			return i + 2;
		case WC_PERCENT:
			sbuffer.append("%");
			return i + 2;
		default:
			throw new IllegalLayoutFormatException("Illegal format exception: " + conversion);
		}
	}

	private class IllegalLayoutFormatException extends RuntimeException {

		private static final long serialVersionUID = 1L;

		public IllegalLayoutFormatException(String arg0) {
			super(arg0);
		}
		
	}
}
